home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 050 / madtrb17.arc / SPELLER.PAS < prev    next >
Pascal/Delphi Source File  |  1985-06-14  |  10KB  |  320 lines

  1. PROGRAM SPELLER;  { SPELL CHECKER -- with cmd line }
  2.  
  3. {   This spell checker is based on the ideas contained in PC-SPELL ver
  4.     1.15 in BASIC by Andy Wildenberg. In that program the text file is
  5.     read into memory and put into a list of words in a string array. The
  6.     string array is then sorted and the unique words removed into
  7.     another array. Thus a unique word array is formed which is in
  8.     alphabetical order. This word list is then compared to a dictionary
  9.     file which is an ASCII list of legal words also in alphabetical
  10.     order. If the word is not found then it is placed into a file of
  11.     possible misspelled words on disk. The user is then responsible for
  12.     printing the list of misspelled words and using a global change
  13.     feature in a word processor to find and replace the words with the
  14.     correct spelling.
  15.  
  16.     This spell checker works in much the same way except that a unique
  17.     word file is formed in an array alphabetically as the text file is
  18.     parsed into words. The rest of the process is about the same.
  19.  
  20.     To use, just type the name of the program followed by parameters
  21.     specifying the source and output files. The parameters are optional
  22.     and if ommitted then the program will request these names.
  23. }
  24.  
  25. CONST
  26.     WORDSIZE : integer = 16;
  27.  
  28. TYPE
  29.     FILES = text;
  30.     STRPARAM = string [255];
  31.     WORDTYP = string [16];
  32.     WORDPTR = ^WORDTYP;
  33.     PTRARRAY = array [0..8000] of WORDPTR; {Limited to 8191 because the
  34.                                  Move function requires an integer parameter
  35.                                  for length in bytes of data to move.}
  36.  
  37. VAR
  38.     SRCNAME : string [36];  { Name of source file to spell check }
  39.     OPPATH : string [24];   { DOS path for speller files }
  40.     OPNAME : string [36];   { DOS name for speller files }
  41.     OUTNAME : string [36];  { Name of output file ( default srcfile.MIS) }
  42.     DOCWORDCNT, UNIQUECNT, MISSPELLCNT : integer;
  43.     I : integer;
  44.     WORDINDX : PTRARRAY;
  45.     WORD, TEMP1 : WORDTYP;
  46.     PREFIX : string [1];
  47.     MATCH : boolean;
  48.     SRCFILE, MISSFILE, DICFILE : FILES;
  49.     x : byte;
  50.     LONGSTRING : string [255]; { working storage for path strings }
  51.  
  52. FUNCTION LOWCASE (var A : char) : boolean;
  53.  
  54. {   LOWCASE modifies the character parameter "A" to make it a lower case
  55.     alpha character if it is an upper case alpha. If the character
  56.     parameter is alpha ('a'..'z' or 'A'..'Z') then the function returns
  57.     TRUE else it returns FALSE. }
  58.  
  59. var x : byte;
  60.  
  61. begin
  62.     x := ord (A);
  63.     if (x>96) and (x<123) then LOWCASE := true
  64.     else begin
  65.         if (x>64) and (x<91) then
  66.         begin
  67.            A := chr (x+32);
  68.            LOWCASE := true;
  69.         end
  70.         else LOWCASE := false;
  71.     end;
  72. end; { of LOWCASE }
  73.  
  74. PROCEDURE GETWORD (var FILNAME : FILES; var WORD : WORDTYP);
  75.  
  76. {GETWORD version 1.2. Defines the start of a word as the next alpha
  77. character in the file. A word is formed by adding characters until a
  78. non-alpha character is found. Contractions are accepted as identified by
  79. a single quote followed by an alpha character occuring after the SOW.
  80. Upper case letters are converted to lower case.}
  81.  
  82. VAR
  83.     CH, CH2 : char;
  84.     SOW : boolean;
  85.     {Global WORDSIZE = maximum word length value.}
  86. begin
  87.     SOW := false;
  88.     WORD := '';
  89.     repeat
  90.        read (FILNAME, CH);
  91.        if LOWCASE (CH) then SOW := true
  92.     until SOW or eof (FILNAME);
  93.     if SOW then
  94.     begin
  95.        WORD := CH;
  96.        repeat
  97.           read (FILNAME, CH);
  98.           if LOWCASE (CH) then
  99.           begin
  100.              if Length (WORD) < WORDSIZE then WORD := WORD + CH
  101.              else SOW := false;
  102.           end
  103.           else begin
  104.              if CH <> '''' then SOW := false
  105.              else begin
  106.                 if not Eof (FILNAME) then
  107.                 begin
  108.                    Read (FILNAME, CH2);
  109.                    if LOWCASE (CH2) then
  110.                    begin
  111.                       if Length (WORD) < WORDSIZE-1 then
  112.                          WORD := WORD + CH + CH2 else SOW := false;
  113.                    end
  114.                    else SOW := false;
  115.                 end;
  116.              end;
  117.           end;
  118.        until (not SOW) or eof (FILNAME);
  119.     end;
  120. end; { of GETWORD }
  121.  
  122. procedure ADDUNIQUE (var LIST : PTRARRAY; WORD : WORDTYP; var TOP : integer);
  123.  
  124. { This procedure does a binary search of the LIST looking for the location
  125.   where WORD belongs. Once it finds the place, if WORD is there then it exits.
  126.   If not, then it moves the list up by one pointer and puts the new word
  127.   there.}
  128.  
  129. var
  130.     SEARCH : boolean;
  131.     MID, LOW, HIGH, COUNT : integer;
  132.  
  133. begin
  134.     SEARCH := true;
  135.     LOW := 0; MID := Trunc (TOP/2); HIGH := TOP;
  136.     while SEARCH do                  {** Find the place where WORD belongs. **}
  137.     begin
  138.        if MID = LOW then SEARCH := false
  139.        else begin
  140.           if WORD < LIST [MID]^ then HIGH := MID
  141.           else LOW := MID;               {** WORD is >= word at LIST [MID]^ **}
  142.           MID := LOW + Trunc ((HIGH-LOW)/2);
  143.        end;
  144.     end; {** of SEARCH. MID is at the location containing WORD or else
  145.               WORD goes at the location after MID. **}
  146.     if WORD <> LIST [MID]^ then begin
  147.        COUNT := 4*(TOP-MID);
  148.        MID := MID+1;
  149.        Move (LIST [MID], LIST [MID+1], COUNT);
  150.        TOP := TOP+1;
  151.        new (LIST [MID]);
  152.        LIST [MID]^ := WORD;
  153.        Gotoxy (20,16);
  154.        Write (TOP);
  155.     end;
  156. end;
  157.  
  158. Function GetPath : STRPARAM;
  159.  
  160. { This procedure extracts the 'PATH =' string from the DOS environment passed
  161. by DOS to the applications program.}
  162.  
  163. Var
  164.     i, x : Integer;
  165.     EnvSegAdr : Integer absolute CSeg : $002c;
  166.     PathString : String [255];
  167.     Done : Boolean;
  168. Begin;
  169.     I := 0;
  170.     PathString := '';
  171.     Done := false;
  172.     Repeat
  173.        x := Mem [EnvSegAdr : I];
  174.        if x <> 0 then begin
  175.           PathString := PathString + chr (x);
  176.           i := i+1;
  177.           end
  178.        else begin
  179.           i := i+1;
  180.           x := Mem [EnvSegAdr : I];
  181.           if x = 0 then done := true;
  182.           if Pos ('PATH',PathString) = 1 then begin
  183.              Done := true;
  184.              PathString := Copy (PathString, 6, Length (PathString));
  185.           end
  186.           else PathString := '';
  187.        end;
  188.     Until Done;
  189. GetPath := PathString;
  190. end;
  191.  
  192. Function ParsePath (Var LONGSTRING : STRPARAM) : STRPARAM;
  193.  
  194. { This function returns the first substring of LONGSTRING which is terminated
  195. by the end of the string or by a semicolon. It then alters the input variable
  196. LONGSTRING to remove this part of the string. Thus subsequent calls to
  197. ParsePath will return one part of the parameter string until it is all gone
  198. and will then return a nul string. }
  199.  
  200. var
  201.     x : integer;
  202. begin
  203.     if length (LONGSTRING) = 0 then ParsePath := '' else begin
  204.        x := Pos (';',LONGSTRING);
  205.        if x=0 then begin
  206.           ParsePath := LONGSTRING;
  207.           LONGSTRING := '';
  208.        end
  209.        else begin
  210.           ParsePath := Copy (LONGSTRING, 1, x-1);
  211.           LONGSTRING := Copy (LONGSTRING, x+1, Length (LONGSTRING));
  212.        end;
  213.     end;
  214. end;
  215.  
  216. begin {*************** MAIN PROGRAM *******************}
  217.  
  218. DOCWORDCNT := 0; MISSPELLCNT := 0;
  219. clrscr;
  220. gotoxy (10,10);
  221. if ParamCount = 0 then begin
  222.     write ('name of source file : ');
  223.     readln (SRCNAME);
  224.     end
  225. else SRCNAME := ParamStr (1);
  226. clrscr;
  227. gotoxy (10,10);
  228. write ('Opening file :  ');
  229. gotoxy (26,10);
  230. writeln (SRCNAME,'                 ');
  231. assign (SRCFILE, SRCNAME);
  232. reset (SRCFILE);
  233. LONGSTRING := GetPath;
  234. MATCH := false;
  235. OPPATH := '';
  236. PREFIX := '';
  237. while MATCH = false do begin
  238.    OPNAME := OPPATH + PREFIX + 'SPELLER.LIS';
  239.    gotoxy (26,10);
  240.    write (OPNAME,'              ');
  241.    assign (DICFILE, OPNAME);
  242.    {$I-} reset (DICFILE) {$I+};
  243.    x := IOResult;
  244.    MATCH := (x=0);
  245.    OPPATH := ParsePath (LONGSTRING);
  246.    if OPPATH = '' then MATCH := true
  247.    else begin
  248.       if (Pos (':',OPPATH) = Length (OPPATH)) or
  249.          (Pos ('\',OPPATH) = Length (OPPATH)) then PREFIX := ''
  250.       else PREFIX := '\';
  251.    end;
  252. end;
  253. if x<>0 then begin
  254.    writeln;
  255.    writeln ('Unable to locate the spelling list. Aborting SPELLER.');
  256.    close (SRCFILE);
  257.    exit;
  258. end;
  259. I := Pos ('.',SRCNAME);
  260. if I = 0 then OUTNAME := SRCNAME + '.MIS'
  261.          else OUTNAME := Copy (SRCNAME, 1, I-1) + '.MIS';
  262. gotoxy (26,10);
  263. write (OUTNAME,'                 ');
  264. assign (MISSFILE, OUTNAME);
  265. {$I-} rewrite (MISSFILE) {$I+};
  266. if IOResult <> 0 then begin
  267.     writeln;
  268.     writeln ('Unable to open the output file. Error code is ',x);
  269.     writeln ('Program terminating.');
  270.     close (SRCFILE);
  271.     close (DICFILE);
  272.     exit;
  273.     end;
  274. Clrscr;
  275. Gotoxy (37,10);
  276. Write ('READING  ',SRCNAME);
  277. Gotoxy (1,14);
  278. Writeln ('WORDS READ      : '); Writeln;
  279. Writeln ('UNIQUE WORDS    : ');Writeln;
  280. Writeln ('WORDS CHECKED   : ');Writeln;
  281. Write   ('SPELLING ERRORS : ');
  282. UNIQUECNT := 1;
  283. New (WORDINDX [1]);
  284. WORDINDX [2] := nil;
  285. WORDINDX [1]^ := '~';
  286. while not eof (SRCFILE) do begin
  287.     GETWORD (SRCFILE, WORD);
  288.     if WORD <> '' then begin
  289.         Gotoxy (20,14);
  290.         DOCWORDCNT := DOCWORDCNT + 1;
  291.         Write (DOCWORDCNT);
  292.         ADDUNIQUE (WORDINDX, WORD, UNIQUECNT);
  293.     end;
  294. end;
  295. Close (SRCFILE);
  296. {*** Check against dictionary ***}
  297. Gotoxy (30,10);
  298. write ('CHECKING SPELLING                ');
  299. I := 1;
  300. WORD := '';
  301. while I <= UNIQUECNT do begin
  302.     Gotoxy (20,18);
  303.     write (I);
  304.     while (WORD < WORDINDX [I]^) and not Eof (DICFILE) do
  305.        Readln (DICFILE, WORD);
  306.     if WORD <> WORDINDX [I]^ then begin
  307.        Writeln (MISSFILE, WORDINDX [I]^);
  308.        MISSPELLCNT := MISSPELLCNT +1;
  309.        Gotoxy (20,20);
  310.        Write (MISSPELLCNT);
  311.     end;
  312.     I := I + 1;
  313. end { while I <= ... };
  314. Close (DICFILE);
  315. Write (MISSFILE, Chr (26));
  316. Close (MISSFILE);
  317. Gotoxy (1,22);
  318. End.  
  319. 
  320.